/**
 * @file syscall.c
 * @date 23.05.01
 * @author xin
 * @brief 系统调用相关处理函数，包括系统调用、参数获取等
 * @version 0.1
 * @status Stable
*/

#include "types.h"
#include "defs.h"
#include "syscall.h"
#include "proc.h"

int
fetchaddr(uint64 addr, uint64 *ip)
{
    struct proc *p = myproc();
    if (addr >= p->sz || addr+sizeof(uint64) > p->sz)
        return -1;  //溢出
    if (copyin(p->pagetable, (char*)ip, addr, sizeof(*ip)) != 0)
        return -1;
    return 0;
}

int
fetchstr(uint64 addr, char* buf, int max)
{
    struct proc *p = myproc();
    if (copyinstr(p->pagetable, buf, addr, max) < 0)
        return -1;
    return strlen(buf);
}

/**
 * @brief 直接从trapframe获取原生参数
 * @param n 第几个参数
 * @return 第n个参数的uint64形式，若n超过6出错
*/
static uint64
argraw(int n)
{
    struct proc *p = myproc();
    switch (n)
    {
    case 0:
        return p->trapframe->a0;
    case 1:
        return p->trapframe->a1;
    case 2:
        return p->trapframe->a2;
    case 3:
        return p->trapframe->a3;
    case 4:
        return p->trapframe->a4;
    case 5:
        return p->trapframe->a5;
    default:
        panic("argraw");
        return -1;
    }
}

void
argint(int n, int* ip)
{
    *ip = argraw(n);
}

void
argaddr(int n, uint64* ip)
{
    *ip = argraw(n);
}

int
argstr(int n, char* buf, int max)
{
    uint64 addr;
    argaddr(n, &addr);
    return fetchstr(addr, buf, max);
}

extern uint64 sys_exec(void);
// extern uint64 sys_exit(void);
extern uint64 sys_write(void);

/**
 * @brief 系统调用函数数组，由syscall()函数调用具体哪个系统调用函数
 * @return 具体的系统调用函数的返回值
*/
static uint64 (*syscalls[])(void) = {
    [SYS_exec]  sys_exec,
    // [SYS_exit]  sys_exit,
    [SYS_write] sys_write,
};

void
syscall(void)
{
    int num;
    struct proc *p = myproc();

    // trapframe->a7存储了系统调用号
    num = p->trapframe->a7;
    // num非零，且在syscalls[]数组的范围内存在
    if (num > 0 && num < NELEM(syscalls) && syscalls[num]) {
        p->trapframe->a0 = syscalls[num]();
    } else {
        printf("%d %s: unknown system call %d\n", p->pid, p->name, num);
        p->trapframe->a0 = -1;
    }
}